package br.com.cpqd.ssar.utilitarias;

import java.util.LinkedList;

public class Cilindro extends AtributosGeometria {

    private float height;
    private float radius;
    private Triangulo[] listaTriangulos = null;
    private LinkedList listVertex = new LinkedList();
    private LinkedList listTriangles = new LinkedList();
    private float step = (3.1415f / 8.0f); // Approximate the cylinder wall with

    /**
     * 
     * @param radius
     * @param height
     * @param reference
     * @param id
     */
    public Cilindro(float radius, float height, float[] reference, int id) {
        super(reference, id);
        this.height = height;
        this.radius = radius;
    }

    /**
     * Retorna a altura do Cilindro
     * @return height
     */
    public float getAltura() {
        return height;
    }

    /**
     * Seta a altura do Cilindro
     * @param height
     */
    public void setAltura(float height) {
        this.height = height;
    }

    /**
     * 
     * @return
     */
    public float getRaio() {
        return radius;
    }

    /**
     * 
     * @param radius
     */
    public void setRaio(float radius) {
        this.radius = radius;
    }

    /**
     * 
     * @return 
     */
    public Triangulo[] triangularizarGeometria() {

        listTriangles.clear();
        listVertex.clear();
        float x = 0, y = 0, angle = 0; // Used to calculate cylinder
        //float height = 75.0f; // Height of the cylinder
        //float diameter = 20.0f; // Diameter of the cylinder
        float h = -height;
        float raio = radius;
        //vertice do centro base 1
        Vertice vertexCentro = new Vertice(referencial);
        //vertex = new Vertice(0.0f + this.getXBegin(), 0.0f + this.getYBegin(), 0.0f + this.getZBegin());
        listVertex.add(vertexCentro);
        /* calculando os vertices da base 1 */
        for (angle = 0.0f; angle < (2.0f * 3.1415f); angle += step) {
            // Calculate x and y position of the next vertex
            x = raio * (float) Math.sin(angle);
            y = raio * (float) Math.cos(angle);
            float[] coordenada = new float[3];
            coordenada[0] = referencial[0] + x;
            coordenada[1] = referencial[1] + y;
            coordenada[2] = referencial[2] + 0;
            Vertice vertex = new Vertice(coordenada);
            //vertex = new Vertice(x + this.getXBegin(), y + this.getYBegin(), 0 + this.getZBegin());
            listVertex.add(vertex);

        }

        /* triangularizando a 1 base */
        Vertice vertexBase = (Vertice) listVertex.get(0); //recebe o vertice 0 (centro)

        for (int i = 1; i < 17; i++) {
            Vertice vertexAux = (Vertice) listVertex.get(i);
            Vertice vertexAux2 = (Vertice) listVertex.get(i + 1);
            //calculando a normal dos 3 vertices
            float[] vectorNormal = super.calcVetorNormal(vertexBase, vertexAux, vertexAux2);
            Vertice[] vectorV = new Vertice[3];
            vectorV[0] = vertexBase;
            vectorV[1] = vertexAux;
            vectorV[2] = vertexAux2;
            Triangulo triangleFace = new Triangulo(vectorV, vectorNormal);
            vectorNormal = new float[3];
            vectorV = new Vertice[3];
            listTriangles.add(triangleFace);
        }

        /* calculando os vertices da base 2 */
        for (angle = 0.0f; angle < (2.0f * 3.1415f); angle += step) {
            // Calculate x and y position of the next vertex
            x = raio * (float) Math.sin(angle);
            y = raio * (float) Math.cos(angle);
            float[] coordenada = new float[3];
            coordenada[0] = referencial[0] + x;
            coordenada[1] = referencial[1] + y;
            coordenada[2] = -h + referencial[2];
            Vertice vertex = new Vertice(coordenada);
            listVertex.add(vertex);

        }

        float[] coordenada = new float[3];
        coordenada[0] = referencial[0] + x;
        coordenada[1] = referencial[1] + y;
        coordenada[2] = -h + referencial[2];
        Vertice vertexAltura = new Vertice(coordenada);
        coordenada = new float[3];
        listVertex.add(vertexAltura);
        vertexAltura = (Vertice) listVertex.getLast();

        /* triangularizando os vertices da base 2 */
        //vertex = (Vertice) listVertex.get(35); //centro base 2
        //recebe o vertice 0 (centro)
        Vertice vertexBase2 = (Vertice) listVertex.get(35);
        vertexBase2.setCoordenada(1, referencial[1]);
        vertexBase2.setCoordenada(0, referencial[0]);

        for (int j = 18; j < 35; j++) {
            Vertice vertexAux = (Vertice) listVertex.get(j);
            Vertice vertexAux2 = (Vertice) listVertex.get(j + 1);
            //calculando a normal dos 3 vertices
            float[] vectorNormal = super.calcVetorNormal(vertexBase2, vertexAux, vertexAux2);
            Vertice[] vectorV = new Vertice[3];
            vectorV[0] = vertexBase2;
            vectorV[1] = vertexAux;
            vectorV[2] = vertexAux2;
            Triangulo triangleFace = new Triangulo(vectorV, vectorNormal);
            vectorNormal = new float[3];
            listTriangles.add(triangleFace);
        }

        /* triangularizando os lados do cilindro */
        int v2 = 18;
        int v3 = 2;
        for (int v1 = 1; v1 < 18; v1++) {
            Vertice vertex = (Vertice) listVertex.get(v1);
            Vertice vertexAux = (Vertice) listVertex.get(v2);
            Vertice vertexAux2 = (Vertice) listVertex.get(v3);
            //calculando a normal dos 3 vertices
            float[] vectorNormal = super.calcVetorNormal(vertex, vertexAux, vertexAux2);
            Vertice[] vectorV = new Vertice[3];
            vectorV[0] = vertex;
            vectorV[1] = vertexAux;
            vectorV[2] = vertexAux2;
            Triangulo triangleFace = new Triangulo(vectorV, vectorNormal);
            vectorNormal = new float[3];
            vectorV = new Vertice[3];
            listTriangles.add(triangleFace);

            Vertice vertex_ = (Vertice) listVertex.get(v2);
            Vertice vertexAux_ = (Vertice) listVertex.get(v3);
            Vertice vertexAux2_ = (Vertice) listVertex.get(v2 + 1);
            //calculando a normal dos 3 vertices
            vectorNormal = super.calcVetorNormal(vertex, vertexAux, vertexAux2);
            vectorV[0] = vertex_;
            vectorV[1] = vertexAux_;
            vectorV[2] = vertexAux2_;
            Triangulo triangleFace_ = new Triangulo(vectorV, vectorNormal);
            listTriangles.add(triangleFace_);
            v2++;
            v3++;
        }

        listaTriangulos = new Triangulo[listTriangles.size()];
        for (int i = 0; i < listTriangles.size(); i++) {
            listaTriangulos[i] = (Triangulo) listTriangles.get(i);
        }

        return listaTriangulos;
    }

    /**
     * 
     * @return listaTriangulos
     */
    public Triangulo[] getListaTriangulos() {
        return listaTriangulos;
    }

    @Override
    public float[] getFirsPoint() {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public float[] getSecondPoint() {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public void setSecondPoint(float[] secondPoint) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public void setFirsPoint(float[] firstPoint) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public int getDiscretizacaoX() {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public void setDiscretizacaoX(int discretizacaoX) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public int getDiscretizacaoY() {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public void setDiscretizacaoY(int discretizacaoY) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public int getDiscretizacaoZ() {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public void setDiscretizacaoZ(int discretizacaoZ) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public double getDx() {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public double getDy() {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public double getDz() {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public int getPmlXi() {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public void setPmlXi(int pmlXi) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public int getPmlXf() {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public void setPmlXf(int pmlXf) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public int getPmlYi() {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public void setPmlYi(int pmlYi) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public int getPmlYf() {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public void setPmlYf(int pmlYf) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public int getPmlZi() {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public void setPmlZi(int pmlZi) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public int getPmlZf() {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public void setPmlZf(int pmlZf) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public double getEscala() {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public void setEscala(double escala) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public void setEscala(String tipo) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public void addX() {
        referencial[0] += 1;
    }

    @Override
    public void addY() {
        referencial[1] += 1;
    }

    @Override
    public void addZ() {
        referencial[2] += 1;
    }

    @Override
    public void subX() {
        this.referencial[0] -= 1;
    }

    @Override
    public void subY() {
        referencial[1] -= 1;
    }

    @Override
    public void subZ() {
        referencial[2] -= 1;
    }

    @Override
    public void redimensionar() {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public String getCaminhoArquivo() {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public void setCaminhoArquivo(String caminhoArquivo) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public int getNSteps() {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public void addX(float valor) {
        referencial[0] += valor;
    }

    @Override
    public void addY(float valor) {
        referencial[1] += valor;
    }

    @Override
    public void addZ(float valor) {
        referencial[2] += valor;
    }

    @Override
    public void setNElements(int n) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public Triangulo[] getListaTriangulosSTL() {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public int getNElements() {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public void redimensionarSTL(float[] min, float[] max) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public void subX(float valor) {
       referencial[0] -= valor;
    }

    @Override
    public void subY(float valor) {
       referencial[1] -= valor;
    }

    @Override
    public void subZ(float valor) {
        referencial[2] -= valor;
    }
}


